package models

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"os"

	"github.com/go-resty/resty/v2"
)

type AliPan struct {
	Host         string
	Path         string
	Key          string
	ClientId     string
	ClientSecret string
}

func (c *AliPan) GetAccessTokenPage() (res string, err error) {
	// 发起授权请求
	resty := resty.New()
	uri := c.Host + c.Path + "?response_type=code&redirect_uri=oob&scope=user:base,file:all:read&client_id=" + c.ClientId
	response, err := resty.R().Get(uri)
	return response.String(), err
}

func (c *AliPan) GetAccessTokenCode() (res string, err error) {
	// 发起授权请求
	resty := resty.New()
	redirect_uri := url.QueryEscape("http://127.0.0.1:9360")
	uri := c.Host + c.Path + "?response_type=code&redirect_uri=" + redirect_uri + "&scope=user:base,file:all:read&client_id=" + c.ClientId
	response, err := resty.R().Get(uri)
	return response.String(), err
}

func (c *AliPan) RefreshAuthentication() (res string, err error) {
	res, err = refreshToken(c)
	// // 设置定时任务，每隔一定时间执行 refreshToken 函数 启动了一个协程
	// go func() {
	// 	for {
	// 		time.Sleep(30 * time.Minute) // 30分钟刷新一次
	// 		// refreshToken(c)
	// 		fmt.Println("")
	// 	}
	// }()
	if err != nil {
		return "", err
	}
	return
}

func (c *AliPan) GetAccessToken() (res string, err error) {
	// 发起授权请求
	resty := resty.New()
	m := make(map[string]string)
	m["client_id"] = c.ClientId
	m["grant_type"] = "authorization_code"
	m["client_secret"] = c.ClientSecret
	m["code"] = "f66f1218cf554d9ebcb320f55eeb4e63"
	response, err := resty.R().
		SetHeader("Content-Type", "application/json").
		SetBody(m).
		Post(c.Host + c.Path)
	// 将获取的access_token写入文件中
	if err != nil {
		return response.String(), err
	}
	var jsonMap map[string]interface{}
	if err := json.Unmarshal(response.Body(), &jsonMap); err != nil {
		return response.String(), err
	}

	// 7200s 两个小时后刷新token

	if jsonMap["access_token"] != "" {
		// 从文件中读取token
		workDir, _ := os.Getwd()
		writeTokenToFile(jsonMap["access_token"].(string), workDir+"/AliPanConfig")
	}

	if jsonMap["refresh_token"] != "" {
		// 从文件中读取token
		workDir, _ := os.Getwd()
		writeTokenToFile(jsonMap["refresh_token"].(string), workDir+"/AliPanRefresh")
	}

	return response.String(), err
}

func (c *AliPan) GetUserInfo() (res string, err error) {
	// 发起授权请求
	resty := resty.New()
	uri := c.Host + c.Path
	// 从文件中读取token
	// 从文件中读取token
	workDir, _ := os.Getwd()
	token, err := readTokenFromFile(workDir + "/AliPanConfig")
	if err != nil {
		return "", err
	}
	response, err := resty.R().
		SetHeader("Authorization", "Bearer "+token).
		SetHeader("Content-Type", "application/json").
		Get(uri)
	return response.String(), err
}

func (c *AliPan) GetUserInfoScopes() (res string, err error) {
	// 发起授权请求
	resty := resty.New()
	uri := c.Host + c.Path
	// 从文件中读取token
	workDir, _ := os.Getwd()
	token, err := readTokenFromFile(workDir + "/AliPanConfig")
	if err != nil {
		return "", err
	}
	response, err := resty.R().
		SetHeader("Authorization", "Bearer "+token).
		SetHeader("Content-Type", "application/json").
		Get(uri)
	return response.String(), err
}

// 获取授权二维码图片的接口
func (c *AliPan) GetAuthQrcode() (res *resty.Response, sid string, err error) {
	// 发起授权请求
	resty := resty.New()
	uri := c.Host + c.Path
	var scopes [2]string = [2]string{"user:base", "file:all:read"}
	m := make(map[string]interface{})
	m["client_id"] = c.ClientId
	m["client_secret"] = c.ClientSecret
	m["scopes"] = scopes
	response, err := resty.R().
		SetBody(m).
		Post(uri)
	if err != nil {
		return nil, "", err
	}
	qrcodeInfo := &QrcodeInfo{}
	err = json.Unmarshal(response.Body(), qrcodeInfo)
	if err != nil {
		return nil, "", err
	}

	qrcodeUri := c.Host + "/oauth/qrcode/" + qrcodeInfo.Sid
	// 将sid写到客户端的cookie中
	response, err = resty.R().Get(qrcodeUri)
	if err != nil {
		return nil, qrcodeInfo.Sid, err
	}
	// 获取图片，直接返回
	return response, qrcodeInfo.Sid, err
}

func (c *AliPan) GetOpenFileList(queryMap map[string]interface{}, passwordFileName string) (res string, err error) {
	// 发起授权请求
	resty := resty.New()
	uri := c.Host + c.Path
	// 从文件中读取token
	workDir, _ := os.Getwd()
	token, err := readTokenFromFile(workDir + "/AliPanConfig")
	if err != nil {
		return "", err
	}
	m := make(map[string]string)
	driveInfoRes, errGetDriveInfo := getDriveInfo(c)
	if errGetDriveInfo != nil {
		return "", err
	}
	driveInfo := &DriveInfo{}
	err = json.Unmarshal(driveInfoRes, driveInfo)
	if err != nil {
		return "", err
	}
	m["drive_id"] = driveInfo.ResourceDriveID
	m["parent_file_id"] = "root"
	if queryMap["drive_id"] != nil && queryMap["drive_id"] != "" {
		m["drive_id"] = queryMap["drive_id"].(string)
	}
	if queryMap["file_id"] != nil && queryMap["file_id"] != "" {
		m["parent_file_id"] = queryMap["file_id"].(string)
	}
	// 变量所有的文件名，找到与配置一样的文件，如果存在就显示该文件访问，需要密码，获取文件详情，拿到密码，进行判断，然后在显示文件夹下面的内容
	response, err := resty.R().
		SetHeader("Authorization", "Bearer "+token).
		SetHeader("Content-Type", "application/json").
		SetBody(m).
		Post(uri)
	// 将json传转map
	fileList := &FileList{}
	if err := json.Unmarshal(response.Body(), fileList); err != nil {
		return "", err
	}
	var file File
	for _, fileItem := range fileList.Files {
		if fileItem.Name == passwordFileName {
			file = fileItem
		}
	}
	if file.Name != "" && (queryMap["password"] == "" || queryMap["password"] == nil) {
		return "405", errors.New("需要输入密码")
	}
	if queryMap["password"] != "" {
		fileQuery := make(map[string]interface{})
		fileQuery["file_id"] = file.FileID
		fileQuery["drive_id"] = file.DriveID
		// 获取文件详情
		fileDetail, err := resty.R().
			SetHeader("Authorization", "Bearer "+token).
			SetHeader("Content-Type", "application/json").
			SetBody(fileQuery).
			Post(c.Host + "/adrive/v1.0/openFile/get")
		if err != nil {
			return "", err
		}
		fileDetailMap := make(map[string]interface{})
		if err := json.Unmarshal(fileDetail.Body(), &fileDetailMap); err != nil {
			return "", err
		}
		if fileDetailMap["url"] != "" && fileDetailMap["url"] != nil {
			fileTextRes, err := resty.R().Get(fileDetailMap["url"].(string))
			if err != nil {
				return "", err
			}
			fmt.Println(fileTextRes.String(), "获取的文本内容是", queryMap["password"], fileTextRes.String() != queryMap["password"])
			if fileTextRes.String() != queryMap["password"] {
				return "405", errors.New("密码输入错误")
			}
		}
	}
	return response.String(), err
}

func getDriveInfo(c *AliPan) (res []byte, err error) {
	// 发起授权请求
	resty := resty.New()
	uri := c.Host + "/adrive/v1.0/user/getDriveInfo"
	// 从文件中读取token
	workDir, _ := os.Getwd()
	token, err := readTokenFromFile(workDir + "/AliPanConfig")
	if err != nil {
		return nil, err
	}
	response, err := resty.R().
		SetHeader("Authorization", "Bearer "+token).
		SetHeader("Content-Type", "application/json").
		Post(uri)
	return response.Body(), err
}

func (c *AliPan) GetAuthQrcodeStatus() (res string, err error) {
	// 发起授权请求
	resty := resty.New()
	uri := c.Host + c.Path
	// 从文件中读取token
	response, err := resty.R().Get(uri)
	return response.String(), err
}

func (c *AliPan) GetFileDetailById(m map[string]interface{}) (res string, err error) {
	// 从文件中读取token
	workDir, _ := os.Getwd()
	token, err := readTokenFromFile(workDir + "/AliPanConfig")
	if err != nil {
		return "", err
	}
	resty := resty.New()
	response, err := resty.R().
		SetHeader("Authorization", "Bearer "+token).
		SetHeader("Content-Type", "application/json").
		SetBody(m).
		Post(c.Host + c.Path)
	return response.String(), err
}

func (c *AliPan) GetFileDownloadLogic(m map[string]interface{}) (res string, err error) {
	// 从文件中读取token
	workDir, _ := os.Getwd()
	token, err := readTokenFromFile(workDir + "/AliPanConfig")
	if err != nil {
		return "", err
	}
	resty := resty.New()
	response, err := resty.R().
		SetHeader("Authorization", "Bearer "+token).
		SetHeader("Content-Type", "application/json").
		SetBody(m).
		Post(c.Host + c.Path)
	return response.String(), err
}

type AliPanRequest struct {
	ClientId     string
	ClientSecret string
	GrantType    string
	Code         string
}

type DriveInfo struct {
	Name            string      `json:"name"`
	Avatar          string      `json:"avatar"`
	UserID          string      `json:"user_id"`
	UserName        string      `json:"user_name"`
	NickName        string      `json:"nick_name"`
	DefaultDriveID  string      `json:"default_drive_id"`
	BackupDriveID   string      `json:"backup_drive_id"`
	ResourceDriveID string      `json:"resource_drive_id"`
	AlbumDriveID    interface{} `json:"album_drive_id"`
}

type AccessTokenInfo struct {
	TokenType    string `json:"token_type"`
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
}

type QrcodeInfo struct {
	QrCodeUrl string `json:"qrCodeUrl"`
	Sid       string `json:"sid"`
}

func readTokenFromFile(filename string) (string, error) {
	tokenBytes, err := os.ReadFile(filename)
	if err != nil {
		return "", err
	}
	token := string(tokenBytes)
	return token, nil
}

// 将token写入文件
func writeTokenToFile(token, filename string) error {
	// 打开文件
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %v", err)
	}
	defer file.Close()
	// 写入token
	_, err = file.WriteString(token)
	if err != nil {
		return fmt.Errorf("failed to write to file: %v", err)
	}
	return nil
}

func refreshToken(c *AliPan) (res string, err error) {
	// 在这里执行刷新token的逻辑
	// 你需要根据你的具体业务实现刷新token的逻辑
	fmt.Println("Refresh token logic here...")
	workDir, _ := os.Getwd()
	refreshTokenValue, err := readTokenFromFile(workDir + "/AliPanRefresh")
	if err != nil {
		return "", err
	}
	// 发起授权请求
	resty := resty.New()
	// 读取refresh_token
	m := make(map[string]string)
	m["client_id"] = c.ClientId
	m["grant_type"] = "refresh_token"
	m["client_secret"] = c.ClientSecret
	m["refresh_token"] = refreshTokenValue
	response, err := resty.R().
		SetHeader("Content-Type", "application/json").
		SetBody(m).
		Post(c.Host + c.Path)
	// 将获取的access_token写入文件中
	if err != nil {
		return response.String(), err
	}
	var jsonMap map[string]interface{}
	if err := json.Unmarshal(response.Body(), &jsonMap); err != nil {
		return response.String(), err
	}

	// 7200s 两个小时后刷新token

	if jsonMap["access_token"] != "" {
		// 从文件中读取token
		workDir, _ := os.Getwd()
		writeTokenToFile(jsonMap["access_token"].(string), workDir+"/AliPanConfig")
	}

	if jsonMap["refresh_token"] != "" {
		// 从文件中读取token
		workDir, _ := os.Getwd()
		writeTokenToFile(jsonMap["refresh_token"].(string), workDir+"/AliPanRefresh")
	}

	return response.String(), err

}
